home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / usenet / volume1 / dots < prev    next >
Encoding:
Internet Message Format  |  1987-07-16  |  60.3 KB

  1. Path: uunet!seismo!husc6!think!ames!ucbcad!ucbvax!decvax!tektronix!tekgen!tekred!games-request
  2. From: games-request@tekred.TEK.COM
  3. Newsgroups: comp.sources.games
  4. Subject: v01i095:  dots - multiplayer dots and boxes game
  5. Message-ID: <1404@tekred.TEK.COM>
  6. Date: 16 Jul 87 00:14:57 GMT
  7. Sender: billr@tekred.TEK.COM
  8. Reply-To: island!argv@sun.com
  9. Lines: 2237
  10. Approved: billr@tekred.TEK.COM
  11.  
  12. Submitted by: Dan Heller <island!argv@sun.com>
  13. Comp.sources.games: Volume 1, Issue 95
  14. Archive-name: dots
  15.  
  16.     [I compiled and ran this.  Fun game, except the computer keeps
  17.      beating me!    -br]
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of shell archive."
  26. # Contents:  Makefile dots.doc dots.h board.c comp.c comp2.c findem.c
  27. #   main.c menu.c misc.c person.c save.c score.c sockt.c
  28. # Wrapped by billr@tekred on Wed Jul 15 17:09:28 1987
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f Makefile -a "${1}" != "-c" ; then 
  31.   echo shar: Will not over-write existing file \"Makefile\"
  32. else
  33. echo shar: Extracting \"Makefile\" \(1912 characters\)
  34. sed "s/^X//" >Makefile <<'END_OF_Makefile'
  35. X#
  36. X# Makefile for dots
  37. X#
  38. X#  Dots and Boxes -- the program for UNIX was programmed by Dan Heller and
  39. X#     Don Hatch Spring, 1984 with further developments continually.
  40. X#  Sockets Implemented by Dan Heller in May, 1985.
  41. X#
  42. X# This program was originally written on a PDP-11 under UNIX V7.  Since
  43. X# then, it has been ported to 4.2BSD and won't work under any thing else
  44. X# altho porting it shouldn't be hard -- just ifdef out the socket stuff.
  45. X#
  46. X# Installation is so easy that there's no need for a README or anything,
  47. X# just edit dots.h and change some of the constants to whatever pathnames
  48. X# you'd like them to be.  Also note DESTDIR here.
  49. X#
  50. X# This code is intended for public consumption and modifications are
  51. X# enoucraged.  If you do make mods, I'd love to hear about them and
  52. X# include in later releases (interest providing).
  53. X#
  54. X# Since everything includes dots.h a make depend is senseless. If you
  55. X# make changes to defines, grep the files to note which are affected
  56. X# and remake them.  If you change variables, use grep on .c files or use
  57. X# "nm" on the .o files to find which files use them.
  58. X#
  59. X# The file "dots.doc" has more information on how to play.
  60. X#
  61. X# comments, etc... to:  Dan Heller
  62. X#    island!argv@sun.com        argv@spam.istc.sri.com
  63. X
  64. XCFLAGS=    -O
  65. XLDFLAGS= -s
  66. XDESTDIR= /usr/games
  67. XLINTFLAGS= -bxah -Dlint
  68. XLIBES = -lcurses -ltermlib
  69. X
  70. XPROG=dots
  71. X
  72. XSRCS=main.c comp.c comp2.c board.c person.c misc.c menu.c save.c score.c \
  73. X     sockt.c findem.c
  74. X
  75. XOBJS=main.o comp.o comp2.o board.o person.o misc.o menu.o save.o score.o \
  76. X     sockt.o findem.o
  77. X
  78. X${PROG}: ${OBJS}
  79. X    @echo Loading...
  80. X    @cc ${LDFLAGS} ${OBJS} ${LIBES} -o ${PROG}
  81. X
  82. Xinstall: ${PROG}
  83. X    /bin/mv ${PROG} ${DESTDIR}/${PROG}
  84. X    chmod 711 ${DESTDIR}/${PROG}
  85. X
  86. Xtags:
  87. X    ctags dots.h ${SRCS}
  88. X
  89. Xclean:
  90. X    rm -f core ${OBJS} ${PROG}
  91. X
  92. Xlint:
  93. X    lint ${LINTFLAGS} ${SRCS}
  94. X
  95. Xtar:
  96. X    tar fcv DOTS Makefile dots.h $(SRCS) tags
  97. X
  98. Xshar:
  99. X    shar Makefile dots.doc dots.h $(SRCS) > dots.shar
  100. END_OF_Makefile
  101. if test 1912 -ne `wc -c <Makefile`; then
  102.     echo shar: \"Makefile\" unpacked with wrong size!
  103. fi
  104. # end of overwriting check
  105. fi
  106. if test -f dots.doc -a "${1}" != "-c" ; then 
  107.   echo shar: Will not over-write existing file \"dots.doc\"
  108. else
  109. echo shar: Extracting \"dots.doc\" \(3304 characters\)
  110. sed "s/^X//" >dots.doc <<'END_OF_dots.doc'
  111. X                         . . .  D  O  T  S  . . .
  112. X
  113. X
  114. X       For points, create squares like this:
  115. X
  116. X                                *---*
  117. X                                | X |
  118. X                                *---*
  119. X
  120. X       Whoever has more squares at the end of the game wins.
  121. X       When a square is won, that player's initial will be
  122. X       put inside the square as shown. 
  123. X
  124. X       To move the cursor, use one of three ways:
  125. X       The "rogue/vi" keys, the number keys or the 
  126. X       keys surrounding the 's'.
  127. X
  128. X       rogue:                         's':                       numbers
  129. X        
  130. X        y k u                        q w e                        7 8 9
  131. X       h     l                      a  s  d                      4     6
  132. X        b j n                        z x c                        1 2 3
  133. X
  134. X       The circle represents which direction you would move away from
  135. X       where the cursor would currently be located.  The numbers are
  136. X       good for terminals that have separate number key pads. The RETURN
  137. X       key or the space-bar will enter a move at the current cursor position.
  138. X
  139. X       When a player enters a move, if he did NOT close any boxes, then
  140. X       it is the other player's turn.  If the player DOES close a box, it
  141. X       remains that players turn and he MUST move again even if he doesn't
  142. X       have another scoring move.
  143. X
  144. X       ^L   will redraw the screen if it gets messed up (or try ^\).
  145. X       'S'  will save your game.
  146. X
  147. X       If you are playing the two player game, that is, another human,
  148. X       not the computer, use the ESCAPE key to 'talk' to the other player.
  149. X       You can ONLY do this when it's your turn. You cannot save games when
  150. X       playing someone else.  There is no high score file for two player games.
  151. X
  152. X       Command line arguments:
  153. X
  154. X       You can see the high-scores without playing by typing:
  155. X
  156. X       % dots -s
  157. X
  158. X       You can restart a saved game by typing:
  159. X
  160. X       % dots -r
  161. X          which will read "dots.save" from your home directory or:
  162. X
  163. X       % dots -r saved_file_name
  164. X       if you've saved it as something other than "dots.save".
  165. X       Be sure to give the full pathname if the file is not in
  166. X       your current directory.
  167. X
  168. X       You can avoid the menu by giving the following information on
  169. X       the command line:
  170. X
  171. X       % dots LENGTH WIDTH LEVEL [C]
  172. X
  173. X          where "length", "width", and "level" are values to use
  174. X          for the length and width of the playing board and level
  175. X      is the level of difficulty to play at (0-3).
  176. X          'C' is the initial to use if you don't want the first
  177. X      letter of your account name in the middle of your squares.
  178. X
  179. X       Example:
  180. X
  181. X       % dots 5 9 0 F
  182. X
  183. X       will play an easy game on a 5 X 9 board and your boxes will be
  184. X       initialized with 'F'.
  185. X
  186. X
  187. X       There is also a way to play others on the system. In the menu,
  188. X       choose the '7' item.  From the command line (avoiding the menu),
  189. X       type:
  190. X
  191. X       % dots 2 login name [tty]
  192. X
  193. X       You may specify the tty if the same user is logged in more than
  194. X       once.  You would use the same format to respond to someone else's
  195. X       request to play you.  When you send (receive) a request, the
  196. X       challenged will get a message every 30 seconds until that user replys 
  197. X       or until the challenger terminates (just like talk).
  198. X
  199. X
  200. END_OF_dots.doc
  201. if test 3304 -ne `wc -c <dots.doc`; then
  202.     echo shar: \"dots.doc\" unpacked with wrong size!
  203. fi
  204. # end of overwriting check
  205. fi
  206. if test -f dots.h -a "${1}" != "-c" ; then 
  207.   echo shar: Will not over-write existing file \"dots.h\"
  208. else
  209. echo shar: Extracting \"dots.h\" \(2367 characters\)
  210. sed "s/^X//" >dots.h <<'END_OF_dots.h'
  211. X/*    dots.h    */
  212. X
  213. X#include <curses.h>
  214. X#include <sys/types.h>
  215. X#include <sys/ioctl.h>
  216. X#ifdef lint
  217. X#include <sys/uio.h>
  218. X#endif lint
  219. X#include <sys/socket.h>
  220. X#include <ctype.h>
  221. X#include <signal.h>
  222. X#include <setjmp.h>
  223. X#include <strings.h>
  224. X
  225. Xextern char *sprintf();
  226. X
  227. X/* Most BSD systems don't have vprintf, but sun versions 3.0 and up do have it.
  228. X * If you're system doesn't have it, comment out the define line. System-V
  229. X * systems do have it, but until this code is ported, it doesn't matter.
  230. X */
  231. X/*#define VPRINTF*/
  232. X
  233. X#define PRIZE        "cigar"
  234. X#define DOCFILE        "/usr/games/lib/dots/dots.doc"
  235. X#define SAVE_FILE    "dots.save"
  236. X#define SCOREFILE    "/usr/games/lib/dots/dots.scores" /* should be full pathname */
  237. X#define version        "Dots version 1.0"
  238. X
  239. X#define when        break;case
  240. X#define otherwise    break;default
  241. X#define Upper(c)    (c = islower(c) ? toupper(c) : c)
  242. X#define Lower(c)    (c = isupper(c) ? tolower(c) : c)
  243. X#define max(a,b)    ((a) > (b) ? (a) : (b))
  244. X#define min(a,b)    ((a) > (b) ? (b) : (a))
  245. X#define erase_char    '\b'
  246. X
  247. X#define ESC        '\033'
  248. X#define DEMO        0
  249. X#define INTERACTIVE    1
  250. X#define TWOPLAYER    2
  251. X#define GOOD        0
  252. X#define BAD        1
  253. X#define DUMB        0
  254. X#define HARD        1
  255. X#define KILLER        2
  256. X#define FREE        0
  257. X#define USED        1
  258. X#define CLOSEDEND    0  /* used for segtype for creating doublecrosses */
  259. X#define OPENEND        1    /* ditto */
  260. X#define MAXL        (COLS / 4)
  261. X#define MAXW        (LINES / 2)
  262. X#define H_MINL        10
  263. X#define H_MINW        10
  264. X#define MINL        4
  265. X#define MINW        4
  266. X#define US        0
  267. X#define THEM        1
  268. X#define SAVE        0
  269. X#define LOAD        1
  270. X#define isodd(a)    ((a)%2)
  271. X#define iseven(a)    (!isodd(a))
  272. X#define ism4(a)        (!((a)%4))
  273. X#define do_twice    for(twicecount=1;twicecount<=2;++twicecount)
  274. X
  275. Xint
  276. X    board[120][120],
  277. X    badboard[120][120],
  278. X    persontally, comptally,
  279. X    Length, Width,
  280. X    xposit, yposit,
  281. X    x_start, y_start,
  282. X    mover,        /* 0 is person/US, 1 is computer/THEM */
  283. X    twicecount,
  284. X    no_good_moves,
  285. X    control_already_established,
  286. X    segtype,    /* OPENEND or CLOSEDEND ; set everytime Howbad is called */
  287. X    dX_found,
  288. X    segflag,
  289. X    mode,
  290. X    level,
  291. X    sd,            /* socket descriptor */
  292. X    jmpbuf_set;
  293. X
  294. Xstruct {
  295. X    int x, y;
  296. X}   Bingo;
  297. X
  298. Xstruct tchars tchars;
  299. X
  300. Xchar *opponent, prize[30], save_file[50], *getenv();
  301. Xchar Initial[2], *username;
  302. Xint onintr(), redraw(), oops();
  303. X
  304. X/* jump to the menu so there's no big stacks (supposedly) */
  305. Xjmp_buf menu_jmp;
  306. X
  307. Xextern int errno;
  308. Xextern char *sys_errlist[], *sys_siglist[];
  309. END_OF_dots.h
  310. if test 2367 -ne `wc -c <dots.h`; then
  311.     echo shar: \"dots.h\" unpacked with wrong size!
  312. fi
  313. # end of overwriting check
  314. fi
  315. if test -f board.c -a "${1}" != "-c" ; then 
  316.   echo shar: Will not over-write existing file \"board.c\"
  317. else
  318. echo shar: Extracting \"board.c\" \(2872 characters\)
  319. sed "s/^X//" >board.c <<'END_OF_board.c'
  320. X/*    board.c    routines that deal with the playing board's display or data */
  321. X
  322. X#include "dots.h"
  323. X
  324. Xsetup()
  325. X{
  326. X    Length = Width = 0;
  327. X    comptally = persontally = 0;
  328. X    xposit = 2, yposit = 1;
  329. X
  330. X    mvprintw(LINES - 6, 0, "Enter LENGTH of board (%d - %d).",
  331. X     (level == DUMB)? MINL : H_MINL, MAXL);
  332. X    do  {
  333. X    mvaddstr(LINES - 4, 0, "->> "), clrtoeol(), refresh();
  334. X    x_start = COLS / 2 - (Length = get_dimensions()) * 2;
  335. X    } while (Length > MAXL || (level == DUMB && Length < MINL) ||
  336. X    (level != DUMB && Length < H_MINL));
  337. X
  338. X    mvprintw(LINES - 6, 0, "Enter WIDTH of board (%d - %d).",
  339. X    (level==DUMB)? MINW:H_MINW, MAXW), clrtoeol();
  340. X    do  {
  341. X    mvaddstr(LINES - 4, 0, "->> "), clrtoeol(), refresh();
  342. X    y_start = LINES / 2 - (Width = get_dimensions());
  343. X    } while (Width > MAXW || (level == DUMB && Width < MINW) ||
  344. X    (level != DUMB && Width < H_MINW));
  345. X
  346. X    mvprintw(LINES - 6, 0, "Length is %d, width is %d.", Length, Width);
  347. X    clrtoeol(), refresh();
  348. X    if (mode == INTERACTIVE)
  349. X    mvprintw(LINES-4, 0,
  350. X        "Your boxes will be initialed with \"%c\"",Initial[US]), clrtoeol();
  351. X    msg("Hit any key to continue. ");
  352. X    getchar();
  353. X}
  354. X
  355. Xfree_board()
  356. X{
  357. X    register int x, y;
  358. X
  359. X    for (x = 0; x <= Length * 2; ++x)
  360. X    for (y = 0; y <= Width * 2; ++y)
  361. X        board[x][y] = FREE;
  362. X    no_good_moves = control_already_established = 0;
  363. X}
  364. X
  365. Xget_dimensions()
  366. X{
  367. X    char          string[10];
  368. X    register char   c;
  369. X    register int    place_on_line = 0, x = 0;
  370. X
  371. X    string[0] = '\0';
  372. X
  373. X    move(LINES - 4, 4), clrtoeol();
  374. X    refresh();
  375. X    while ((c = getchar()) != '\n') {
  376. X    if (c == erase_char || c == '\027')
  377. X        if (place_on_line != 0) {
  378. X        string[--x] = '\0';
  379. X        --place_on_line;
  380. X        addstr("\b \b"); 
  381. X        refresh();
  382. X        } else
  383. X        continue;
  384. X    else if (isdigit(c)) {
  385. X        if (place_on_line == 4)
  386. X        continue;
  387. X        place_on_line++;
  388. X        addch(string[x++] = c);
  389. X        refresh();
  390. X    }
  391. X    }
  392. X    string[x] = '\0';
  393. X    return atoi(string);
  394. X}
  395. X
  396. Xdrawboard()
  397. X{
  398. X    register int x, y;
  399. X
  400. X    clear();
  401. X    for (y = 1; y < 2 * Width; y++)
  402. X    for (x = 1; x < 2 * Length; x++) {
  403. X        move(y_start + (y - 1), x_start + (2 * x - 2));
  404. X        if (iseven(x) && isodd(y) && board[x][y] == USED)
  405. X        addstr("\b---\b\b");
  406. X        if (iseven(y) && isodd(x) && board[x][y] == USED)
  407. X        addch('|');
  408. X        else if (iseven(x) && iseven(y) && closure(GOOD, x, y) == 4) {
  409. X        if (board[x][y] == 1)
  410. X            mover = 1;
  411. X        else
  412. X            mover = 0;
  413. X        putinitial(x, y);
  414. X        } else if (isodd(x) && isodd(y))
  415. X        addch('*');
  416. X    }
  417. X    if (mode == TWOPLAYER) {
  418. X    mvaddstr(LINES - 3, 0, "Your Messages: ");
  419. X    mvprintw(LINES - 2, 0, "%s's Messages: ", opponent);
  420. X    }
  421. X}
  422. X
  423. Xchlevel(c)
  424. X{
  425. X    if (!sure(c))
  426. X    return;
  427. X    level = (level + 1) % 3;
  428. X    bottom_line();
  429. X}
  430. X
  431. Xsure(c)
  432. Xchar c;
  433. X{
  434. X    register int   count;
  435. X    register char  C;
  436. X
  437. X    for (count = 0; count <= 3; ++count)
  438. X    if ((C = getchar()) != c) {
  439. X        ungetc(C, stdin);
  440. X        return FALSE;
  441. X    }
  442. X    return TRUE;
  443. X}
  444. END_OF_board.c
  445. if test 2872 -ne `wc -c <board.c`; then
  446.     echo shar: \"board.c\" unpacked with wrong size!
  447. fi
  448. # end of overwriting check
  449. fi
  450. if test -f comp.c -a "${1}" != "-c" ; then 
  451.   echo shar: Will not over-write existing file \"comp.c\"
  452. else
  453. echo shar: Extracting \"comp.c\" \(8116 characters\)
  454. sed "s/^X//" >comp.c <<'END_OF_comp.c'
  455. X/*    COMP.C    */
  456. X
  457. X#include "dots.h"
  458. X
  459. Xcompmove()
  460. X{
  461. X    bottom_line();
  462. X    close_boxes();
  463. X    if (!board_is_full())
  464. X    if (!find_good_move(GOOD))
  465. X        force_move();
  466. X}
  467. X
  468. Xclose_boxes()
  469. X{
  470. X    Bingo.x = Bingo.y = 0;
  471. X    dX_found = 0;
  472. X    if (level == DUMB || cntrl_not_established() || find_good_move(BAD))
  473. X    close_EVERYTHING();
  474. X    else
  475. X    first_pass();
  476. X}
  477. X
  478. Xfind_good_move(BorG)
  479. Xint BorG;
  480. X{
  481. X    int x, y, xcount, ycount, x1, y1, x2, y2;
  482. X
  483. X    if (no_good_moves)
  484. X    return (0);
  485. X    if (BorG == GOOD && level == KILLER && kill_4_loops())
  486. X    return (1);
  487. X    for (xcount = 1, x = random() % (2 * Length - 1) + 1; xcount < Length * 2;
  488. X    xcount++, x = x % (2 * Length - 1) + 1)
  489. X    for (ycount = 1, y = random() % (2 * Width - 1) + 1; ycount < Width * 2;
  490. X        ycount++, y = y % (2 * Width - 1) + 1) {
  491. X        if (iseven(x + y))
  492. X        continue;
  493. X        if (board[x][y] == USED)
  494. X        continue;
  495. X        find_adj_squares(x, y, &x1, &y1, &x2, &y2);
  496. X        if (closure(GOOD, x1, y1) == 2)
  497. X        continue;
  498. X        if (closure(GOOD, x2, y2) == 2)
  499. X        continue;
  500. X        if (BorG == GOOD) {
  501. X        xposit = x, yposit = y;
  502. X        (void) entermove();
  503. X        }
  504. X        return (1);
  505. X    }
  506. X    no_good_moves = 1;
  507. X    return (0);
  508. X}
  509. X
  510. X/********************************************************************\
  511. X|*   check all dots and ruins potential 4 loops.                    *|
  512. X|*                                                                  *|
  513. X|*      Want to prevent:      Find these:   Before they turn into:  *|
  514. X|*         *---*---*            *---*   *         *---*   *         *|
  515. X|*         |       |            |                |                 *|
  516. X|*         *   *   *            *   *   *         *   *   *         *|
  517. X|*         |       |                      |        *|
  518. X|*         *---*---*            *   *---*         *   *---*         *|
  519. X|*   Because 4 loops lose points and #3 guarantees 4-loops          *|
  520. X\********************************************************************/
  521. X
  522. Xkill_4_loops()
  523. X{
  524. X    int x, y, x1, y1, x2, y2, dx, dy, xcheck, ycheck;
  525. X
  526. X    for (x = 3; x <= 2 * Length - 3; x += 2)
  527. X    for (y = 3; y <= 2 * Width - 3; y += 2) {
  528. X        if (closure(GOOD, x, y))
  529. X        continue;    /* a line is connected to dot */
  530. X        for (dx = -1; dx <= 1; dx += 2)
  531. X        for (dy = -1; dy <= 1; dy += 2)
  532. X            if (closure(GOOD, x + dx, y + dy) == 2)
  533. X            if (closure(GOOD, x - dx, y - dy) == 1) {
  534. X                xcheck = x - dx, ycheck = y;
  535. X                do_twice
  536. X                {
  537. X                find_adj_squares(xcheck, ycheck, &x1, &y1, &x2, &y2);
  538. X                if (closure(GOOD, x1, y1) != 2 && closure(GOOD, x2, y2) != 2) {
  539. X                    xposit = xcheck, yposit = ycheck;
  540. X                    (void) entermove();
  541. X                    return (1);
  542. X                } else
  543. X                    xcheck = x, ycheck = y - dy;
  544. X                }
  545. X            }
  546. X    }
  547. X    return (0);
  548. X}
  549. X
  550. Xforce_move()
  551. X{
  552. X    int x, y, xcount, ycount, x1, y1, x2, y2;
  553. X    int Badness, bestx, besty, Bestbad = 1000, Besttype;
  554. X
  555. X    if (dX_found) {
  556. X    if (comptally + persontally + segflag == OPENEND ? 2 : 4 == (Length - 1) * (Width - 1)) {
  557. X        Bingo.x = Bingo.y = dX_found = 0;
  558. X        close_EVERYTHING();
  559. X        return;
  560. X    }
  561. X    if (segflag == OPENEND) {
  562. X        find_adj_squares(Bingo.x, Bingo.y, &x1, &y1, &x2, &y2);
  563. X        if (closure(GOOD, x1, y1) == 2 && closure(GOOD, x2, y2) == 2) {
  564. X        close_boxes();
  565. X        if (!board_is_full())
  566. X            force_move();
  567. X        return;
  568. X        }
  569. X    }
  570. X    xposit = Bingo.x;
  571. X    yposit = Bingo.y;
  572. X    (void) entermove();
  573. X    return;
  574. X    }
  575. X    for (xcount = 1, x = random() % (2 * Length - 1) + 1; xcount < Length * 2;
  576. X    xcount++, x = x % (2 * Length - 1) + 1)
  577. X    for (ycount = 1, y = random() % (2 * Width - 1) + 1; ycount < Width * 2;
  578. X        ycount++, y = y % (2 * Width - 1) + 1)
  579. X        if (isodd(x + y) && board[x][y] == FREE) {
  580. X        find_adj_squares(x, y, &x1, &y1, &x2, &y2);
  581. X        if (closure(GOOD, x1, y1) != 3 && closure(GOOD, x2, y2) != 3)
  582. X            if ((Badness = Howbad(GOOD, Bestbad, x, y)) < Bestbad) {
  583. X            Bestbad = Badness;
  584. X            bestx = x;
  585. X            besty = y;
  586. X            Besttype = segtype;
  587. X            }
  588. X        }
  589. X    if (Bestbad >= 2 && Besttype == OPENEND)
  590. X    goto_middle_of_path(GOOD, &bestx, &besty);
  591. X    xposit = bestx;
  592. X    yposit = besty;
  593. X    (void) entermove();
  594. X}
  595. X
  596. Xfirst_pass()
  597. X{
  598. X    int x, y, x1, y1, doubleX, doubleY;
  599. X    int Badness;
  600. X    int start_over;
  601. X
  602. X    do {
  603. X    start_over = 0;
  604. X    for (x = 2; x <= 2 * Length - 2 && !start_over; x += 2)
  605. X        for (y = 2; y <= 2 * Width - 2 && !start_over; y += 2)
  606. X        if (closure(GOOD, x, y) == 3) {
  607. X            x1 = x, y1 = y;
  608. X            goto_adj_free_line(GOOD, &x1, &y1);
  609. X            if (((Badness = Howbad(BAD, 1000, x1, y1)) == 2 &&
  610. X                segtype == OPENEND)
  611. X            || (Badness == 4 && segtype == CLOSEDEND)) {
  612. X            segflag = segtype;
  613. X            dX_found = 1;
  614. X            doubleX = x1;
  615. X            doubleY = y1;
  616. X            board[x1][y1] = USED;    /* temporarily */
  617. X            goto_next_square(GOOD, &doubleX, &doubleY);
  618. X            goto_adj_free_line(GOOD, &doubleX, &doubleY);
  619. X            Bingo.x = doubleX;
  620. X            Bingo.y = doubleY;
  621. X            board[x1][y1] = FREE;    /* SIGH */
  622. X            close_EVERYTHING();
  623. X            return;
  624. X            } else if (Badness <= 2) {
  625. X            xposit = x1, yposit = y1;
  626. X            entermove();
  627. X            } else {
  628. X            xposit = x1, yposit = y1;
  629. X            entermove();
  630. X            start_over = 1;
  631. X            }
  632. X        }
  633. X    }
  634. X    while (start_over);
  635. X}
  636. X
  637. Xclose_EVERYTHING()
  638. X{
  639. X    int x, y, x_check, y_check, moved;
  640. X
  641. X    do {
  642. X    moved = 0;
  643. X    for (x = 2; x <= 2 * Length - 2; x += 2)
  644. X        for (y = 2; y <= 2 * Width - 2; y += 2)
  645. X        if (closure(GOOD, x, y) == 3) {
  646. X            x_check = x, y_check = y;
  647. X            goto_adj_free_line(GOOD, &x_check, &y_check);
  648. X            /* at the end of the game, ignore this line! */
  649. X            if (!board_is_almost_full() && too_close(x_check, y_check))
  650. X            continue;
  651. X            xposit = x_check;
  652. X            yposit = y_check;
  653. X            entermove();
  654. X            moved = 1;
  655. X        }
  656. X    }
  657. X    while (moved);
  658. X}
  659. X
  660. XHowbad(BorG, Max, xmove, ymove)
  661. Xint BorG, Max, xmove, ymove;
  662. X{
  663. X    int x, y, x1, y1, x2, y2, moved, badtotal = 0;
  664. X
  665. X    for (x = 1; x < 2 * Length; x++)
  666. X    for (y = isodd(x) ? 2 : 1; y < 2 * Width; y += 2)
  667. X        badboard[x][y] = board[x][y];
  668. X    if (BorG == GOOD)
  669. X    badboard[xmove][ymove] = USED;
  670. X    segtype = OPENEND;
  671. X
  672. X    do_twice {
  673. X    x = xmove;
  674. X    y = ymove;
  675. X    do {
  676. X        moved = 0;
  677. X        if (!goto_next_square(BAD, &x, &y))
  678. X        break;
  679. X        goto_adj_free_line(BAD, &x, &y);
  680. X        badboard[x][y] = USED;
  681. X        moved = 1;
  682. X        find_adj_squares(x, y, &x1, &y1, &x2, &y2);
  683. X        if (closure(BAD, x1, y1) == 4 && closure(BAD, x2, y2) == 4)
  684. X        badtotal++, segtype = CLOSEDEND;    /* add extra for two
  685. X                             * sides */
  686. X        badtotal++;
  687. X        if (badtotal >= Max)
  688. X        return (Max);
  689. X    }
  690. X    while (moved == 1);
  691. X    }
  692. X    return (badtotal);
  693. X}
  694. X
  695. X/***********************************************************************\
  696. X|*  This procedure returns true if the line passed is on either of the *|
  697. X|*  boxes next to Bingo.                                               *|
  698. X\***********************************************************************/
  699. X
  700. Xtoo_close(x, y)
  701. Xint x, y;
  702. X{
  703. X    if (abs(x - Bingo.x) == 1 && abs(y - Bingo.y) == 1) {    /* REAL close */
  704. X    if (isodd(Bingo.x)) {    /* Bingo is vertical  */
  705. X        if (closure(GOOD, x, Bingo.y) == 2)
  706. X        return (1);
  707. X    } else {    /* Bingo is horizontal */
  708. X        if (closure(GOOD, Bingo.x, y) == 2)
  709. X        return (1);
  710. X    }
  711. X    }
  712. X    if (isodd(Bingo.x)) {    /* Bingo is vertical  */
  713. X    if ((abs(x - Bingo.x) == 2 && y == Bingo.y)
  714. X        && (closure(GOOD, (x + Bingo.x) / 2, y) == 2))
  715. X        return (1);
  716. X    } else {        /* Bingo is horizontal */
  717. X    if ((abs(y - Bingo.y) == 2 && x == Bingo.x)
  718. X        && (closure(GOOD, x, (y + Bingo.y) / 2) == 2))
  719. X        return (1);
  720. X    }
  721. X    return (0);
  722. X}
  723. X
  724. X/***************************************************************************\
  725. X|* This function decides if there are still more open-ended paths of       *|
  726. X|* length two or less still on the board. If there are, it returns 1, else *|
  727. X|* 0.                                                                      *|
  728. X\***************************************************************************/
  729. X
  730. Xcntrl_not_established()
  731. X{
  732. X    int x, y, x1, y1, x2, y2;
  733. X
  734. X    if (control_already_established)
  735. X    return (0);
  736. X    for (x = 1; x < 2 * Length; x++)
  737. X    for (y = isodd(x) ? 2 : 1; y < 2 * Width; y += 2)
  738. X        if (board[x][y] == FREE)
  739. X        if (Howbad(GOOD, 3, x, y) <= 2 && segtype == OPENEND) {
  740. X            find_adj_squares(x, y, &x1, &y1, &x2, &y2);
  741. X            if (closure(GOOD, x1, y1) <= 2 && closure(GOOD, x2, y2) <= 2)
  742. X            return (1);
  743. X        }
  744. X    control_already_established = 1;
  745. X    return (0);
  746. X}
  747. END_OF_comp.c
  748. if test 8116 -ne `wc -c <comp.c`; then
  749.     echo shar: \"comp.c\" unpacked with wrong size!
  750. fi
  751. # end of overwriting check
  752. fi
  753. if test -f comp2.c -a "${1}" != "-c" ; then 
  754.   echo shar: Will not over-write existing file \"comp2.c\"
  755. else
  756. echo shar: Extracting \"comp2.c\" \(2257 characters\)
  757. sed "s/^X//" >comp2.c <<'END_OF_comp2.c'
  758. X/*    COMP2.C    */
  759. X
  760. X#include "dots.h"
  761. X
  762. Xgoto_next_square(BorG, x, y)    /* returns 1 if there is one, 0 if not */
  763. Xint BorG, *x, *y;
  764. X{
  765. X    int x1, y1, x2, y2;
  766. X
  767. X    find_adj_squares(*x, *y, &x1, &y1, &x2, &y2);
  768. X    if (x1 != NULL && closure(BorG, x1, y1) == 3) {
  769. X    *x = x1, *y = y1;
  770. X    return (1);
  771. X    }
  772. X    if (x2 != NULL && closure(BorG, x2, y2) == 3) {
  773. X    *x = x2, *y = y2;
  774. X    return (1);
  775. X    }
  776. X    return (0);
  777. X}
  778. X
  779. Xfind_adj_squares(x, y, x1, y1, x2, y2)
  780. Xint x, y, *x1, *y1, *x2, *y2;
  781. X{
  782. X    if (isodd(x)) {    /* Vertical line */
  783. X    *x1 = x - 1;
  784. X    *y1 = y;
  785. X    *x2 = x + 1;
  786. X    *y2 = y;
  787. X    } else {        /* Horizontal line */
  788. X    *x1 = x;
  789. X    *y1 = y - 1;
  790. X    *x2 = x;
  791. X    *y2 = y + 1;
  792. X    }
  793. X    if (!is_on_board(*x1, *y1))
  794. X    *x1 = NULL, *y1 = NULL;
  795. X    if (!is_on_board(*x2, *y2))
  796. X    *x2 = NULL, *y2 = NULL;
  797. X}
  798. X
  799. Xgoto_adj_free_line(BorG, x, y)
  800. Xint BorG;
  801. Xint *x, *y;
  802. X{
  803. X    int xtemp, ytemp;
  804. X
  805. X    for (xtemp = *x - 1; xtemp <= *x + 1; xtemp += 2)
  806. X    if ((BorG == BAD ? badboard[xtemp][*y] : board[xtemp][*y]) == FREE) {
  807. X        *x = xtemp;
  808. X        return;
  809. X    }
  810. X    for (ytemp = *y - 1; ytemp <= *y + 1; ytemp += 2)
  811. X    if (board[*x][ytemp] == FREE)
  812. X        if (((BorG == BAD)? badboard[*x][ytemp] : board[*x][ytemp])
  813. X            == FREE) {
  814. X        *y = ytemp;
  815. X        return;
  816. X        }
  817. X    printf("You fucked up, buddy!");
  818. X    fflush(stdout);
  819. X    die();
  820. X}
  821. X
  822. X/*****************************************************************************\
  823. X|*  right now, this function doesn't actually go to the middle of a path,    *|
  824. X|*  it simply goes one line away from the edge. If the length of the path is *|
  825. X|*  two, the effect is the same.                                             *|
  826. X\*****************************************************************************/
  827. Xgoto_middle_of_path(BorG, x, y)
  828. Xint BorG, *x, *y;
  829. X{
  830. X    int origx, origy, x1, y1, x2, y2;
  831. X
  832. X    find_adj_squares(*x, *y, &x1, &y1, &x2, &y2);
  833. X    if (closure(BorG, x1, y1) == 2 && closure(BorG, x2, y2) == 2)
  834. X    return;        /* you're sitting on it to begin with */
  835. X    origx = *x, origy = *y;
  836. X    if (BorG == GOOD)
  837. X    board[origx][origy] = USED;
  838. X    else
  839. X    badboard[origx][origy] = USED;
  840. X    /* Temporarily */
  841. X    goto_next_square(BorG, x, y);
  842. X    goto_adj_free_line(BorG, x, y);
  843. X
  844. X    if (BorG == GOOD)
  845. X    board[origx][origy] = FREE;
  846. X    else
  847. X    badboard[origx][origy] = FREE;
  848. X    /* SIGH! */
  849. X}
  850. END_OF_comp2.c
  851. if test 2257 -ne `wc -c <comp2.c`; then
  852.     echo shar: \"comp2.c\" unpacked with wrong size!
  853. fi
  854. # end of overwriting check
  855. fi
  856. if test -f findem.c -a "${1}" != "-c" ; then 
  857.   echo shar: Will not over-write existing file \"findem.c\"
  858. else
  859. echo shar: Extracting \"findem.c\" \(1475 characters\)
  860. sed "s/^X//" >findem.c <<'END_OF_findem.c'
  861. X/* findem.c   find the login of the person we wanna play */
  862. X
  863. X#include "dots.h"
  864. X#include <sys/stat.h>
  865. X#include <sgtty.h>
  866. X#include <utmp.h>
  867. X
  868. X#define UTMP          "/etc/utmp"
  869. X
  870. Xstruct utmp utmp_buf;
  871. Xstruct stat stat_buf;
  872. Xstruct sgttyb sgtty_buf;
  873. X
  874. Xint fd;
  875. X
  876. Xfindem(argc, argv)
  877. Xchar **argv;
  878. X{
  879. X    char *ttyname(), to_tty[13];
  880. X    register char *login = argv[2], *where = "", *ourtty = ttyname(0) + 5;
  881. X    register FILE *recipient;
  882. X
  883. X    if (argc > 3)
  884. X    where = argv[3];
  885. X    if (!strcmp(where, ourtty)) {
  886. X    fprintf(stderr, "You can't play yourself.\n");
  887. X    return 0;
  888. X    }
  889. X    if ((fd = open(UTMP, 0)) == -1) {
  890. X    perror(UTMP);
  891. X    return 0;
  892. X    }
  893. X
  894. X    while (read(fd, (char *) &utmp_buf, sizeof(utmp_buf)))
  895. X    if (!strcmp(utmp_buf.ut_name, login) &&
  896. X       (*where && !strcmp(utmp_buf.ut_line, where) ||
  897. X       (!*where && strcmp(where, ourtty))))
  898. X        break;
  899. X
  900. X    (void) close(fd);
  901. X    if (strcmp(login, utmp_buf.ut_name)) {
  902. X    fprintf(stderr, "%s is not logged in.", login);
  903. X    return 0;
  904. X    }
  905. X    if (*where && strcmp(where, utmp_buf.ut_line)) {
  906. X    fprintf(stderr, "%s is not logged in on %s.\n", login, where);
  907. X    return 0;
  908. X    }
  909. X
  910. X    (void) sprintf(to_tty, "/dev/%s", utmp_buf.ut_line);
  911. X    if (!(recipient = fopen(to_tty, "w"))) {
  912. X    perror(to_tty);
  913. X    fprintf(stderr, "%s: Can't ask %s to play.\n", argv[0], argv[2]);
  914. X    return 0;
  915. X    }
  916. X    setuid(getuid());    /* turns off set-uid attribute once tty is opened */
  917. X    setgid(getgid());    /* probably isn't necessary most of the time */
  918. X
  919. X    return invite(recipient);
  920. X}
  921. END_OF_findem.c
  922. if test 1475 -ne `wc -c <findem.c`; then
  923.     echo shar: \"findem.c\" unpacked with wrong size!
  924. fi
  925. # end of overwriting check
  926. fi
  927. if test -f main.c -a "${1}" != "-c" ; then 
  928.   echo shar: Will not over-write existing file \"main.c\"
  929. else
  930. echo shar: Extracting \"main.c\" \(5156 characters\)
  931. sed "s/^X//" >main.c <<'END_OF_main.c'
  932. X/*    MAIN.C    */
  933. X
  934. X#include "dots.h"
  935. X
  936. Xchar *error_msg[] = {
  937. X    "usages:\n",
  938. X    "%s -s        gives top scores.\n",
  939. X    "%s -d        reads the directions\n",
  940. X    "%s -r [file]    restart saved game (from file if given).\n",
  941. X    "%s L W D [C]    plays a game using integer arguments as\n",
  942. X    "            Length, Width and Difficulty levels, respectively.\n",
  943. X    "            'C' is inital for boxes.\n",
  944. X    "%s 2 user [tty]    send request/reply to play someone else (2-user).\n",
  945. X    "\nsetenv DOTSOPTS \"name=whoareyou,savefile=path,initial=X,prize=whatever\"\n",
  946. X    0
  947. X};
  948. X
  949. Xchar *getusername();
  950. X
  951. Xbus_n_seg(sig)
  952. X{
  953. X    if (sig == SIGBUS)
  954. X    fprintf(stderr, "Bus error.\n");
  955. X    else
  956. X    fprintf(stderr, "Segmentation Fault.\n");
  957. X    die();
  958. X}
  959. X
  960. Xmain(argc, argv)
  961. Xint argc;
  962. Xchar **argv;
  963. X{
  964. X    register char *p;
  965. X    extern char *UP;
  966. X
  967. X    setbuf(stdout, (char *)NULL);
  968. X    setbuf(stderr, (char *)NULL);
  969. X
  970. X    username = getusername();
  971. X
  972. X    savetty();
  973. X    initscr();
  974. X
  975. X    (void) signal(SIGBUS,  bus_n_seg);
  976. X    (void) signal(SIGSEGV, bus_n_seg);
  977. X    (void) signal(SIGINT,  onintr);
  978. X    (void) signal(SIGPIPE, onintr);
  979. X    (void) signal(SIGCHLD, SIG_IGN); /* to return from shell esc */
  980. X    (void) signal(SIGQUIT, redraw);
  981. X
  982. X    if (argc > 1 && argv[1][0] == '-' && argv[1][1] != 'r')
  983. X    if (argv[1][1] == 'd')
  984. X        readinst(1), exit(0);
  985. X    else if (argv[1][1] == 's')
  986. X        high_score(TRUE, FALSE), die();
  987. X    else if (argv[1][1] == 'x')
  988. X        high_score(TRUE, TRUE), die();
  989. X    else
  990. X        do_error(argv[0]), die();
  991. X
  992. X    if (COLS < 4 * H_MINL || LINES < 2 * H_MINW) {
  993. X    printf("Window must be at least %d by %d.\n", 4 * H_MINL, 2 * H_MINW);
  994. X    die();
  995. X    }
  996. X    if (!*UP) {
  997. X    printf("You need cursor movement capability on your terminal.\n");
  998. X    die();
  999. X    }
  1000. X
  1001. X    srandom(getpid());
  1002. X    mover = US, Initial[THEM] = '$';
  1003. X    getopts();
  1004. X    noecho(), crmode();
  1005. X
  1006. X    if (argc > 1)
  1007. X    parse_command(argc, argv);
  1008. X    else
  1009. X    menu();
  1010. X}
  1011. X
  1012. Xdo_error(arg)
  1013. Xchar *arg;
  1014. X{
  1015. X    int count = 0;
  1016. X
  1017. X    while (error_msg[count])
  1018. X    fprintf(stderr, error_msg[count++], arg);
  1019. X    die();
  1020. X}
  1021. X
  1022. XDots(which)    /* which? recovered game, start from command line, or menu */
  1023. Xint which;    /* 0 = start from beginning, 1 = recovered game */
  1024. X{
  1025. X    Upper(Initial[US]);
  1026. X    Lower(Initial[THEM]);
  1027. X
  1028. X    if (mode == TWOPLAYER) {
  1029. X    mvprintw(LINES-5,0, "Your label is '%c' and %s's is '%c'.",
  1030. X                    Initial[US], opponent, Initial[THEM]);
  1031. X    mvprintw(LINES-4,0, "%s will go first.", (mover==US)? "You" : opponent);
  1032. X    mvaddstr(LINES-3,0, "^Z stops game for you only. \"fg\" resumes game.");
  1033. X    mvaddstr(LINES-2,0, "ESC to talk to other player. ^L to redraw board.");
  1034. X    msg("--hit any key to continue-- ");
  1035. X    getchar();
  1036. X    set_redraw_signal_key_to('\014');    /* change to ^L */
  1037. X    free_board();
  1038. X    }
  1039. X    if (!which)        /* could be a restart of a saved game  or  a new game */
  1040. X    setup(), free_board();
  1041. X    drawboard();
  1042. X    while (!board_is_full())
  1043. X    if (mode != DEMO && (mode == TWOPLAYER || mover == US))
  1044. X        mover = (personmove()) ? mover : !mover; /* switch if we got some */
  1045. X    else if (mode != TWOPLAYER && (mode == DEMO || mover == THEM))
  1046. X        if (!board_is_full())
  1047. X        compmove(), mover = !mover;
  1048. X    end_of_game();
  1049. X}
  1050. X
  1051. Xgetopts()
  1052. X{
  1053. X    char *p, *opts, temp[BUFSIZ], *length, *index();
  1054. X
  1055. X    (void) strcpy(prize, PRIZE);
  1056. X    (void) strcpy(save_file, SAVE_FILE);
  1057. X    if (opts = getenv("DOTSOPTS")) {
  1058. X    length = opts + strlen(opts);
  1059. X    while (opts < length) {
  1060. X        (void) sscanf(opts, "%[^,]", temp);
  1061. X        if (p = index(temp, '='))
  1062. X        if (!strncmp(temp, "name", 4))
  1063. X            username = ++p;
  1064. X        else if (!(strncmp(temp, "savefile", 8)))
  1065. X            (void) strcpy(save_file, ++p);
  1066. X        else if (!(strncmp(temp, "prize", 5)))
  1067. X            (void) strcpy(prize, ++p);
  1068. X        else if (!(strncmp(temp, "initial", 7)))
  1069. X            Initial[US] = *++p;
  1070. X        opts += 1 + strlen(temp);
  1071. X    }
  1072. X    }
  1073. X    if (!Initial[US])
  1074. X    Initial[US] = *username;
  1075. X}
  1076. X
  1077. Xparse_command(argc, argv)
  1078. Xint argc;
  1079. Xchar **argv;
  1080. X{
  1081. X    if (!strcmp(argv[1], "2")) {
  1082. X    if (argc < 3)
  1083. X        printf(error_msg, argv[0]);
  1084. X    else
  1085. X        mode = TWOPLAYER, sockit(argc, argv);
  1086. X    die();
  1087. X    }
  1088. X
  1089. X    mode = INTERACTIVE;
  1090. X
  1091. X    if (!strcmp(argv[1], "-r")) {
  1092. X    if (argc == 3)
  1093. X        (void) strcpy(save_file, argv[2]);
  1094. X    if (recover(1))
  1095. X        Dots(1);
  1096. X    else
  1097. X        die();
  1098. X    menu();
  1099. X    }
  1100. X
  1101. X    if (argc < 4)
  1102. X    do_error(argv[0]);
  1103. X
  1104. X    if ((level = atoi(argv[3])) < DUMB || level > KILLER) {
  1105. X    printf("%s: Invalid Difficulty Level (0,1, or 2)\n", argv[0]);
  1106. X    die();
  1107. X    }
  1108. X    if ((Length = atoi(argv[1])) > MAXL || Length < (level? H_MINL : MINL)) {
  1109. X    printf("%s: (%d) Invalid Length.\n", argv[0], Length);
  1110. X    die();
  1111. X    }
  1112. X    if ((Width = atoi(argv[2])) > MAXW || Width < (level? H_MINW : MINW)) {
  1113. X    printf("%s: (%d) Invalid Width.\n", argv[0], Width);
  1114. X    die();
  1115. X    }
  1116. X
  1117. X    if (argc > 4)
  1118. X    Initial[US] = *argv[4];
  1119. X    comptally = persontally = 0;
  1120. X    xposit = 2, yposit = 1;
  1121. X    y_start = 1 + LINES / 2 - Width;
  1122. X    x_start = 1 + COLS / 2 - Length * 2;
  1123. X    Dots(2);
  1124. X}
  1125. X
  1126. X#include <pwd.h>
  1127. Xchar *
  1128. Xgetusername()
  1129. X{
  1130. X    struct passwd *entry;
  1131. X    extern char *getlogin();
  1132. X    register char *p;
  1133. X
  1134. X    if ((p = getenv("NAME"))
  1135. X    || (p = getenv("SIGNATURE"))
  1136. X    || (p = getenv("USER"))
  1137. X    || (p = getlogin()))
  1138. X    return p;
  1139. X    if (!(entry = getpwuid(getuid())))
  1140. X    puts("Who the hell are you?"), die();
  1141. X    endpwent();
  1142. X    return entry->pw_name;
  1143. X}
  1144. END_OF_main.c
  1145. if test 5156 -ne `wc -c <main.c`; then
  1146.     echo shar: \"main.c\" unpacked with wrong size!
  1147. fi
  1148. # end of overwriting check
  1149. fi
  1150. if test -f menu.c -a "${1}" != "-c" ; then 
  1151.   echo shar: Will not over-write existing file \"menu.c\"
  1152. else
  1153. echo shar: Extracting \"menu.c\" \(4094 characters\)
  1154. sed "s/^X//" >menu.c <<'END_OF_menu.c'
  1155. X/*    MENU.C    */
  1156. X
  1157. X#include "dots.h"
  1158. X#include <utmp.h>
  1159. X#include <sys/stat.h>
  1160. X
  1161. X#define ever (;;)
  1162. X
  1163. Xmenu()
  1164. X{
  1165. X    int c, command = 1;
  1166. X
  1167. X    jmpbuf_set = 1;
  1168. X    (void) setjmp(menu_jmp);
  1169. X    disp_menu();
  1170. X    for ever {
  1171. X    while ((c = getchar()) != '\n')
  1172. X        if (c > '0' && c < '9')
  1173. X        putchar(c), putchar('\b'), command = c;
  1174. X    switch (command - '0') {
  1175. X        case 1: readinst(0), disp_menu();
  1176. X        when 2: level = DUMB, mode = INTERACTIVE, Dots(0);
  1177. X        when 3: level = HARD, mode = INTERACTIVE, Dots(0);
  1178. X        when 4: level = KILLER, mode = INTERACTIVE, Dots(0);
  1179. X        when 5: level = DUMB, mode = DEMO, Dots(0);
  1180. X        when 6: if (recover(0)) Dots(1);
  1181. X        when 7: challenge();
  1182. X        when 8: goodbye(1);
  1183. X    }
  1184. X    }
  1185. X}
  1186. X
  1187. Xdisp_menu()
  1188. X{
  1189. X    int partition = LINES / 10, lines;
  1190. X
  1191. X    clear();
  1192. X    mvaddstr((lines = partition + LINES - 10 * partition), COLS / 2 - 10, ". . . D O T S . . .");
  1193. X    mvaddstr((lines += partition), COLS / 6, "1. Read instructions.");
  1194. X    mvaddstr((lines += partition), COLS / 6, "2. Easy game.");
  1195. X    mvaddstr((lines += partition), COLS / 6, "3. Hard game.");
  1196. X    mvaddstr((lines += partition), COLS / 6, "4. Killer game.");
  1197. X    mvaddstr((lines = partition + LINES - 9 * partition), 4 * COLS / 6, "5. Demo game.");
  1198. X    mvaddstr((lines += partition), 4 * COLS / 6, "6. Recover saved game.");
  1199. X    mvaddstr((lines += partition), 4 * COLS / 6, "7. Play someone else.");
  1200. X    mvaddstr((lines += partition), 4 * COLS / 6, "8. Leave game.");
  1201. X    mvaddstr((lines += partition), COLS / 2 - 9, "Enter command. [ ]\b\b");
  1202. X    refresh();
  1203. X}
  1204. X
  1205. Xreadinst(before)
  1206. Xbool before;        /* before or after curses mode has been set */
  1207. X{
  1208. X    int c, line_count = 0;
  1209. X    FILE *fp2;
  1210. X
  1211. X    if (!before)
  1212. X    clear(), refresh();
  1213. X    else
  1214. X    noecho(), crmode();
  1215. X    if ((fp2 = fopen(DOCFILE, "r")) == NULL)
  1216. X    perror(DOCFILE);
  1217. X    else {
  1218. X    while ((c = getc(fp2)) != EOF) {
  1219. X        putchar(c);
  1220. X        if (c == '\n')
  1221. X        line_count++;
  1222. X        if (line_count == LINES - 1) {
  1223. X        printf("--more--(or 'q' to return)");
  1224. X        if (getchar() == 'q') {
  1225. X            fclose(fp2);
  1226. X            if (before)
  1227. X            echo(), nocrmode();
  1228. X            return;
  1229. X        }
  1230. X        printf("\015                          \015");
  1231. X        line_count = 0;
  1232. X        }
  1233. X    }
  1234. X    fclose(fp2);
  1235. X    }
  1236. X    if (!before) {
  1237. X    printf("Hit return to continue [ ]\b\b");
  1238. X    while (getchar() != '\n');
  1239. X    } else
  1240. X    echo(), nocrmode();
  1241. X}
  1242. X
  1243. Xwritable(line)
  1244. Xchar *line;
  1245. X{
  1246. X    char ttyno[20];
  1247. X
  1248. X    sprintf(ttyno, "/dev/%s", line);
  1249. X    return !access(ttyno, 02);
  1250. X}
  1251. X
  1252. Xchallenge()
  1253. X{
  1254. X    struct utmp buf;
  1255. X    int count = 0, col = LINES / 3, l_len = 0;
  1256. X    char *p, *index(), *victim[4], string[20], *ttyname(), *tty = ttyname(0)+5;
  1257. X    FILE *file;
  1258. X
  1259. X    victim[0] = "Dots";
  1260. X    victim[1] = "2";
  1261. X    clear();
  1262. X    mvaddstr(col, 0, "Here are your potential opponents: ");
  1263. X    move(++col, 0);
  1264. X
  1265. X    if ((file = fopen("/etc/utmp", "r")) == NULL) {
  1266. X    disp_menu();
  1267. X    msg("/etc/utmp: %s", sys_errlist[errno]);
  1268. X    return;
  1269. X    }
  1270. X    while (fread((char *)&buf, sizeof(struct utmp), 1, file) > 0)
  1271. X    if (buf.ut_name[0] && writable(buf.ut_line)) {
  1272. X        if (!strncmp(buf.ut_name, username, 8) && !strcmp(buf.ut_line, tty))
  1273. X        continue;
  1274. X        if (count++)
  1275. X        addstr(", ");
  1276. X        if ((l_len + 10 + min(strlen(buf.ut_name), 8)) > COLS - 1)
  1277. X        clrtoeol(), move(++col, 0), l_len = 0;
  1278. X        l_len += 10 + min(strlen(buf.ut_name), 8);
  1279. X        printw("%-.8s (%s)", buf.ut_name, buf.ut_line);
  1280. X    }
  1281. X    (void) fclose(file);
  1282. X    if (!count) {
  1283. X    disp_menu();
  1284. X    msg("There doesn't seem to be anyone who can play.");
  1285. X    return;
  1286. X    }
  1287. X    mvaddstr(col += 2, 0, "RETURN for menu.");
  1288. X    mvaddstr(++col, 0, "Whom would you like to play (user [ttyxx])? ");
  1289. X    refresh();
  1290. X    count = 2;
  1291. X    Getstr(string, min(20, COLS - 1));
  1292. X    if (string[0] == NULL) {
  1293. X    disp_menu();
  1294. X    return;
  1295. X    }
  1296. X    move(++col, 0);
  1297. X    refresh();
  1298. X    victim[count++] = string;
  1299. X    if ((p = index(string, ' ')) != NULL) {
  1300. X    *(p++) = '\0';
  1301. X    victim[count - 1] = string;
  1302. X    victim[count++] = p;
  1303. X    }
  1304. X    mode = TWOPLAYER;
  1305. X    sockit(count, victim); /* shouldn't return. If so, there was an error */
  1306. X    mode = DEMO;
  1307. X    putchar('\n'); /* don't overwrite any error messages */
  1308. X    msg("Hit any key to continue.");
  1309. X    getchar();
  1310. X    disp_menu();
  1311. X}
  1312. END_OF_menu.c
  1313. if test 4094 -ne `wc -c <menu.c`; then
  1314.     echo shar: \"menu.c\" unpacked with wrong size!
  1315. fi
  1316. # end of overwriting check
  1317. fi
  1318. if test -f misc.c -a "${1}" != "-c" ; then 
  1319.   echo shar: Will not over-write existing file \"misc.c\"
  1320. else
  1321. echo shar: Extracting \"misc.c\" \(6276 characters\)
  1322. sed "s/^X//" >misc.c <<'END_OF_misc.c'
  1323. X/*    MISC.C    */
  1324. X
  1325. X#include "dots.h"
  1326. X
  1327. X/* has to be a function instead of define because signal calls this */
  1328. Xredraw()
  1329. X{
  1330. X    clearok(curscr, TRUE), wrefresh(curscr);
  1331. X}
  1332. X
  1333. X/* returns the number of boxes closed, if any */
  1334. Xentermove()
  1335. X{
  1336. X    Cursor(xposit, yposit);
  1337. X    addstr(iseven(yposit) ? "|\b" : "\b---\b\b");
  1338. X    board[xposit][yposit] = USED;
  1339. X    return he_got_some();
  1340. X}
  1341. X
  1342. Xclosure(BorG, x, y)
  1343. Xregister int BorG, x, y;
  1344. X{
  1345. X    if (!is_on_board(x, y))
  1346. X    return (-1);
  1347. X    if (BorG == GOOD)
  1348. X    return (board[x][y - 1]
  1349. X        + board[x][y + 1]
  1350. X        + board[x - 1][y]
  1351. X        + board[x + 1][y]);
  1352. X    else
  1353. X    return (badboard[x][y - 1]
  1354. X        + badboard[x][y + 1]
  1355. X        + badboard[x - 1][y]
  1356. X        + badboard[x + 1][y]);
  1357. X}
  1358. X
  1359. Xhe_got_some()
  1360. X{
  1361. X    int total = 0, x1, y1, x2, y2;
  1362. X
  1363. X    find_adj_squares(xposit, yposit, &x1, &y1, &x2, &y2);
  1364. X    if (closure(GOOD, x1, y1) == 4) {
  1365. X    putinitial(x1, y1);
  1366. X    total++;
  1367. X    }
  1368. X    if (closure(GOOD, x2, y2) == 4) {
  1369. X    putinitial(x2, y2);
  1370. X    total++;
  1371. X    }
  1372. X    if (mover == THEM)
  1373. X    comptally += total;
  1374. X    else
  1375. X    persontally += total;
  1376. X    bottom_line();
  1377. X
  1378. X    return total;
  1379. X}
  1380. X
  1381. Xset_redraw_signal_key_to(c)
  1382. Xchar c;
  1383. X{
  1384. X    static char oldquit = 0;
  1385. X
  1386. X    if (!oldquit)
  1387. X    if (ioctl(0, TIOCGETC, &tchars) == -1)
  1388. X        oops("ioctl get call");
  1389. X    else
  1390. X        oldquit = tchars.t_quitc;
  1391. X    tchars.t_quitc = (c) ? c : oldquit;    /* redraw screen anytime by signal */
  1392. X    if (ioctl(0, TIOCSETC, &tchars) == -1)
  1393. X    oops("ioctl set call");
  1394. X}
  1395. X
  1396. Xbottom_line()
  1397. X{
  1398. X    char line[128], Opponent[12];
  1399. X    register char *p = line;
  1400. X
  1401. X    (void) sprintf(Opponent, "%s's", opponent);
  1402. X    if (mode != DEMO)
  1403. X    p += strlen(sprintf(p, "%8s turn.    ",
  1404. X        (mover == US) ? "Your" : (mode == TWOPLAYER) ? Opponent : "My"));
  1405. X    p += strlen(sprintf(p, "%s: %3d    %s: %3d     ",
  1406. X    (mode == DEMO) ? "Player 1" : "You",
  1407. X    persontally, (mode == TWOPLAYER) ? opponent :
  1408. X    (mode == DEMO) ? "Player 2" : "Me", comptally));
  1409. X    if (mode != TWOPLAYER && mode != DEMO && strlen(line) + 13 < COLS - 1)
  1410. X    p += strlen(sprintf(p, "Level: %s ",
  1411. X        (level == DUMB) ? "EASY" : (level == HARD) ? "HARD" : "KILLER"));
  1412. X    if (p - line + 14 < COLS - 1 && mode != DEMO)
  1413. X    p += strlen(sprintf(p, "   '?' for help."));
  1414. X    if (mode == DEMO)
  1415. X    p += strlen(sprintf(p, "            Demo Game."));
  1416. X    if (mode == TWOPLAYER && p - line + 29 < COLS - 1)
  1417. X    (void) sprintf(p, "  '^L' to redraw.  ESC to talk.");
  1418. X    msg(line);
  1419. X    Cursor(xposit, yposit);
  1420. X}
  1421. X
  1422. Xboard_is_almost_full()
  1423. X{
  1424. X    return (persontally + comptally >= (Length - 1) * (Width - 1) - 4);
  1425. X}
  1426. X
  1427. Xboard_is_full()
  1428. X{
  1429. X    return (persontally + comptally == (Length - 1) * (Width - 1));
  1430. X}
  1431. X
  1432. Xend_of_game()
  1433. X{
  1434. X    char line[80], c;
  1435. X    register char *p = line;
  1436. X
  1437. X    move(LINES - 1, 0);
  1438. X    if (board_is_full()) {
  1439. X    p += strlen(sprintf(p, "Score: %d to %d.  ", comptally, persontally));
  1440. X    if (comptally == persontally)
  1441. X        p += strlen(sprintf(p, "No one won.  "));
  1442. X    else if (mode == DEMO)
  1443. X        p += strlen(sprintf(p, "%s won.  ", (comptally > persontally)
  1444. X        ? "Player 2" : "Player 1"));
  1445. X    else
  1446. X        p += strlen(sprintf(p, "%s won.  ",
  1447. X        (comptally > persontally) ? (mode == TWOPLAYER) ?
  1448. X        "They" : "I" : "You"));
  1449. X    addstr(line);
  1450. X    if (mode != DEMO)
  1451. X        if (comptally - persontally < 0) {
  1452. X        printw("You get a %s. ", prize);
  1453. X        if (mode != TWOPLAYER)
  1454. X            high_score(0, 0);
  1455. X        } else if (comptally != persontally)
  1456. X        printw("You lose a %s. ", prize);
  1457. X    } else
  1458. X    addstr("No score, you quit.");
  1459. X    if (mode == TWOPLAYER)
  1460. X    goodbye(1);
  1461. X    addstr("--more--"), clrtoeol();
  1462. X    refresh();
  1463. X    getchar();
  1464. X    msg("RETURN for menu; 'Q' to exit. ");
  1465. X    if ((c = getchar()) == 'q' || c == 'Q')
  1466. X    goodbye(1);
  1467. X    disp_menu();
  1468. X}
  1469. X
  1470. Xgoodbye(When)
  1471. Xbool When;
  1472. X{
  1473. X    if (When)
  1474. X    msg("");
  1475. X    if (When && mode != TWOPLAYER)
  1476. X    high_score(TRUE, FALSE);
  1477. X    printf("\nThanx, %s.\n", username);
  1478. X    die();
  1479. X}
  1480. X
  1481. X/*VARARGS1*/
  1482. Xmsg(fmt, args)
  1483. Xchar *fmt;
  1484. X{
  1485. X    char string[BUFSIZ];
  1486. X#ifdef VPRINTF
  1487. X    vsprintf(string, fmt, &args);
  1488. X#else
  1489. X    FILE foo;
  1490. X    foo._cnt = BUFSIZ;
  1491. X    foo._base = foo._ptr = string; /* may have to be cast(unsigned char *) */
  1492. X    foo._flag = _IOWRT+_IOSTRG;
  1493. X    _doprnt(fmt, &args, &foo);
  1494. X    (void) fputc(0, &foo);
  1495. X#endif VPRINTF
  1496. X    mvaddstr(LINES-1, 0, string), clrtoeol(), refresh();
  1497. X}
  1498. X
  1499. X/*VARARGS1*/
  1500. Xoops(fmt, args)
  1501. Xchar *fmt;
  1502. X{
  1503. X#ifdef VPRINTF
  1504. X    vprintf(fmt, &args);
  1505. X#else
  1506. X    _doprnt(fmt, &args, stdout);
  1507. X#endif VPRINTF
  1508. X    perror("");
  1509. X}
  1510. X
  1511. Xdie()
  1512. X{
  1513. X    set_redraw_signal_key_to(0);    /* reset to original, whatever it was */
  1514. X    if (mode == TWOPLAYER)
  1515. X    destroysocket();
  1516. X    nocrmode(), echo(), endwin();
  1517. X    exit(0);
  1518. X}
  1519. X
  1520. Xonintr(sig)
  1521. X{
  1522. X    int x, y;
  1523. X
  1524. X    (void) signal(sig, onintr);
  1525. X    (void) alarm(0);
  1526. X    if (sig != SIGPIPE) {
  1527. X    getyx(stdscr, y, x);
  1528. X    msg("Really quit? ");
  1529. X    if (getchar() != 'y') {
  1530. X        move(y, x);
  1531. X        if (Length && Width)
  1532. X        bottom_line();
  1533. X        else
  1534. X        refresh();
  1535. X        return;
  1536. X    }
  1537. X    }
  1538. X    msg("");
  1539. X    if (sig != SIGINT && sig != SIGQUIT) {
  1540. X    if (sig == SIGPIPE)
  1541. X        destroysocket(), fprintf(stderr, "Your opponent terminated.\n");
  1542. X    else
  1543. X        printw("I got signal #%d: %s", sig, sys_siglist[sig]);
  1544. X    clrtoeol();
  1545. X    refresh();
  1546. X    }
  1547. X    if (jmpbuf_set && sig != SIGINT && sig != SIGQUIT)
  1548. X    longjmp(menu_jmp, 1);
  1549. X    die();
  1550. X}
  1551. X
  1552. XCursor(a, b)
  1553. Xint a, b;
  1554. X{
  1555. X    move(y_start + b - 1, x_start + a * 2 - 2), refresh();
  1556. X}
  1557. X
  1558. Xis_on_board(x, y)
  1559. Xregister int x, y;
  1560. X{
  1561. X    return (x > 0 && y > 0 && x < 2 * Length && y < 2 * Width);
  1562. X}
  1563. X
  1564. Xputinitial(x, y)
  1565. Xregister int x, y;
  1566. X{
  1567. X    Cursor(x, y);
  1568. X    addch(Initial[mover]);
  1569. X    refresh();
  1570. X    board[x][y] = mover;
  1571. X}
  1572. X
  1573. Xshell()
  1574. X{
  1575. X    register char     *SHELL;
  1576. X    register int    pid, w;
  1577. X    int         status, (*oq)(), (*oi)();
  1578. X
  1579. X    clear(), refresh();
  1580. X    printf("Which Shell, (sh / csh (s/c))? ");
  1581. X    SHELL = (getchar() == 'c') ? "/bin/csh" : "/bin/sh";
  1582. X    echo(), nocrmode();
  1583. X
  1584. X    oi = signal(SIGINT, SIG_IGN);  /* old interrupt (oi) and old quit (oq) */
  1585. X    oq = signal(SIGQUIT, SIG_IGN); /* signals saved on return of signal() */
  1586. X
  1587. X    if ((pid = fork()) == 0) {
  1588. X    setuid(getuid());
  1589. X    setgid(getgid());
  1590. X    execl(SHELL, SHELL, 0);
  1591. X    oops("Couldn't execl(%s)", SHELL);
  1592. X    _exit(127);
  1593. X    }
  1594. X    while ((w = wait(&status)) != pid && w != -1)
  1595. X    ;
  1596. X    printf("[Hit return to continue]");
  1597. X    while (getchar() != '\n')
  1598. X    ;
  1599. X
  1600. X    (void) signal(SIGINT, oi);    /* reset old signals */
  1601. X    (void) signal(SIGQUIT, oq);
  1602. X    noecho(), crmode();
  1603. X    drawboard(), bottom_line();
  1604. X    return (status);
  1605. X}
  1606. END_OF_misc.c
  1607. if test 6276 -ne `wc -c <misc.c`; then
  1608.     echo shar: \"misc.c\" unpacked with wrong size!
  1609. fi
  1610. # end of overwriting check
  1611. fi
  1612. if test -f person.c -a "${1}" != "-c" ; then 
  1613.   echo shar: Will not over-write existing file \"person.c\"
  1614. else
  1615. echo shar: Extracting \"person.c\" \(3768 characters\)
  1616. sed "s/^X//" >person.c <<'END_OF_person.c'
  1617. X/*    PERSON.C    */
  1618. X
  1619. X#include "dots.h"
  1620. X
  1621. X#define ever (;;)
  1622. X
  1623. Xpersonmove()
  1624. X{
  1625. X    char c;
  1626. X    int fd = ((mover == US) ? 0 : sd);
  1627. X
  1628. X    Cursor(xposit, yposit);    /* do this so raw mode won't destroy screen */
  1629. X    raw();
  1630. X    noraw();        /* flush type-ahead */
  1631. X    bottom_line();
  1632. X    do  {
  1633. X    for ever {
  1634. X        if (read(fd, &c, 1) <= 0)
  1635. X        onintr(SIGPIPE);    /* someone terminated */
  1636. X        if (mode == TWOPLAYER)
  1637. X        if (c == '!' || c == 'S' || c == '.' || c == '/' || c == 'Q')
  1638. X            continue;
  1639. X        else if (c != 'r' && fd != sd)
  1640. X            (void) write(sd, &c, 1);    /* send info to other player */
  1641. X        if (c == '\n' || c == ' ')
  1642. X        break;
  1643. X        Cursor(xposit, yposit);
  1644. X        switch (c) {
  1645. X        case ESC:
  1646. X            if (mode == TWOPLAYER)
  1647. X                talk();
  1648. X
  1649. X        when '?':
  1650. X            if (mover == US)
  1651. X            readinst(0), drawboard();
  1652. X            if (mode == TWOPLAYER)
  1653. X            if (mover == THEM) {
  1654. X                msg("%s is reading the instructions.", opponent);
  1655. X                if (read(fd, &c, 1) <= 0)    /* wait for a char */
  1656. X                onintr(SIGPIPE);
  1657. X            } else
  1658. X                (void) write(sd, &c, sizeof(c));
  1659. X            bottom_line();
  1660. X        when '!':
  1661. X            if (shell() == -1)
  1662. X            perror("shell");
  1663. X        when 'Q':
  1664. X            if (mode != TWOPLAYER)
  1665. X            end_of_game();
  1666. X            else
  1667. X            onintr(SIGPIPE);
  1668. X        when 'S': Save_game();
  1669. X        when 'r': redraw();
  1670. X            when '7': case 'q': case 'y':
  1671. X            if (is_on_board(xposit - 1, yposit - 1))
  1672. X                xposit -= 1, yposit -= 1;
  1673. X            when '8': case 'w': case 'k':
  1674. X            if (is_on_board(xposit, yposit - 2))
  1675. X                yposit -= 2;
  1676. X            when '9': case 'e': case 'u':
  1677. X            if (is_on_board(xposit + 1, yposit - 1))
  1678. X                xposit += 1, yposit -= 1;
  1679. X            when '4': case 'a': case 'h':
  1680. X            if (is_on_board(xposit - 2, yposit))
  1681. X                xposit -= 2;
  1682. X            when '6': case 'd': case 'l':
  1683. X            if (is_on_board(xposit + 2, yposit))
  1684. X                xposit += 2;
  1685. X            when '1': case 'z': case 'b':
  1686. X            if (is_on_board(xposit - 1, yposit + 1))
  1687. X                xposit -= 1, yposit += 1;
  1688. X            when '2': case 'x': case 'j':
  1689. X            if (is_on_board(xposit, yposit + 2))
  1690. X                yposit += 2;
  1691. X            when '3': case 'c': case 'n':
  1692. X            if (is_on_board(xposit + 1, yposit + 1))
  1693. X                xposit += 1, yposit += 1;
  1694. X        when '.': chlevel(c);
  1695. X        }
  1696. X        Cursor(xposit, yposit);
  1697. X    }
  1698. X    if (board[xposit][yposit] == USED && mover == US) {
  1699. X        mvaddstr(LINES - 1, 0, "It's taken.   ");
  1700. X        Cursor(xposit, yposit);
  1701. X    }
  1702. X    }
  1703. X    while (board[xposit][yposit] == USED);
  1704. X    return entermove();
  1705. X}
  1706. X
  1707. X#define Addch(c)    addch(c); if (mode == TWOPLAYER) (void) write(sd, &c, 1)
  1708. X#define backspace() Addch(back_char); Addch(space); Addch(back_char); refresh()
  1709. X
  1710. XGetstr(String, length)
  1711. Xchar *String;
  1712. Xint length;
  1713. X{
  1714. X    char garbage, space = ' ', back_char = erase_char;
  1715. X    int count = 0;
  1716. X
  1717. X    while ((garbage = getchar()) != '\n' && garbage != 4 && garbage != ESC)
  1718. X    if (garbage == _tty.sg_erase && count) {
  1719. X        backspace();
  1720. X        String[count--] = 0;
  1721. X    } else if (garbage == _tty.sg_kill && count)
  1722. X        do {
  1723. X        backspace();
  1724. X        } while (--count);
  1725. X    else if (garbage == '\027' && count)    /* ^W */
  1726. X        do  {
  1727. X        backspace();
  1728. X        String[count--] = 0;
  1729. X        if (!count || (String[count-1]==' ' && !isspace(String[count])))
  1730. X            break;
  1731. X        } while (count);
  1732. X    else if (count == length)
  1733. X        fputc('\007', stderr);
  1734. X    else if (garbage > 31 && garbage != 127) {
  1735. X        String[count++] = garbage;
  1736. X        Addch(garbage);
  1737. X        refresh();
  1738. X    }
  1739. X    String[count] = 0;
  1740. X}
  1741. X
  1742. Xtalk()
  1743. X{
  1744. X    char c, dummy[128], cr = '\n';
  1745. X    int nread = 0;
  1746. X
  1747. X    if (mover == US) {
  1748. X    move(LINES - 3, 15);
  1749. X    clrtoeol(), refresh();
  1750. X    Getstr(dummy, COLS - 16);
  1751. X    (void) write(sd, &cr, 1);
  1752. X    } else {
  1753. X    move(LINES - 2, strlen(opponent) + 3 + strlen("Messages: "));
  1754. X    clrtoeol();
  1755. X    refresh();
  1756. X    while ((nread = read(sd, &c, 1)) > 0 && c != cr)
  1757. X        addch(c), refresh();
  1758. X    if (nread == -1)
  1759. X        oops("bad socket read");
  1760. X    }
  1761. X}
  1762. END_OF_person.c
  1763. if test 3768 -ne `wc -c <person.c`; then
  1764.     echo shar: \"person.c\" unpacked with wrong size!
  1765. fi
  1766. # end of overwriting check
  1767. fi
  1768. if test -f save.c -a "${1}" != "-c" ; then 
  1769.   echo shar: Will not over-write existing file \"save.c\"
  1770. else
  1771. echo shar: Extracting \"save.c\" \(5455 characters\)
  1772. sed "s/^X//" >save.c <<'END_OF_save.c'
  1773. X/*  SAVE.C  */
  1774. X
  1775. X#include "dots.h"
  1776. X
  1777. XSave_game()
  1778. X{
  1779. X    int c;
  1780. X    FILE *fp;
  1781. X    char buf[40];
  1782. X
  1783. X    buf[0] = 0;
  1784. X
  1785. X    msg("File: %s? ", save_file);
  1786. X    if ((c = getchar()) != 'Y' && c != 'y') {
  1787. X    if (c != ESC) {
  1788. X        msg("File: ");
  1789. X        Getstr(buf, min(40, COLS - 8));
  1790. X        if (strlen(buf) > 1)
  1791. X        (void) strcpy(save_file, buf);
  1792. X    }
  1793. X    } else
  1794. X    (void) strcpy(buf, save_file);
  1795. X    if (*buf)
  1796. X    if (!(fp = fopen(buf, "w"))) {
  1797. X        msg("Couldn't open %s: %s --more--", save_file, sys_errlist[errno]);
  1798. X        while (getchar() != ' ')
  1799. X        fputc(7, stderr);
  1800. X    } else {
  1801. X        c = save(fp, SAVE);
  1802. X        (void) fclose(fp);
  1803. X        if (c)
  1804. X        fputc('\n', stdout), die();
  1805. X    }
  1806. X    bottom_line();
  1807. X}
  1808. X
  1809. Xrecover(before)
  1810. Xbool before;
  1811. X{
  1812. X    int c, xspot, yspot;
  1813. X    FILE *fp;
  1814. X
  1815. X    if (!before) {
  1816. X    getyx(stdscr, yspot, xspot);
  1817. X    msg("File: %s? ", save_file);
  1818. X    if ((c = getchar()) != 'Y' && c != 'y')
  1819. X        if (c != ESC) {
  1820. X        char buf[40];
  1821. X        msg("Input Filename: ");
  1822. X        Getstr(buf, min(40, COLS - 17));
  1823. X        move(LINES - 1, 0);
  1824. X        refresh();
  1825. X        if (strlen(buf) < 2) {
  1826. X            move(yspot, xspot);
  1827. X            refresh();
  1828. X            return 0;
  1829. X        } else
  1830. X            (void) strcpy(save_file, buf);
  1831. X        } else
  1832. X        return 0;
  1833. X    }
  1834. X    if (!(fp = fopen(save_file, "r")))
  1835. X    if (before)
  1836. X        perror(save_file);
  1837. X    else
  1838. X        msg("Couldn't open %s: %s", save_file, sys_errlist[errno]);
  1839. X    else if (save(fp, LOAD)) {
  1840. X    (void) fclose(fp);
  1841. X    if (unlink(save_file) < 0)
  1842. X        oops("Couldn't unlink savefile"), puts("Are you trying to cheat?");
  1843. X    return 1;
  1844. X    } else {
  1845. X    (void) fclose(fp);
  1846. X    if (before)
  1847. X        putchar('\n'), die();
  1848. X    }
  1849. X    if (!before)
  1850. X    move(yspot, xspot), refresh();
  1851. X    return 0;
  1852. X}
  1853. X
  1854. Xsave(fp, funct)
  1855. XFILE *fp;
  1856. X{
  1857. X    register int x, y;
  1858. X    int i;
  1859. X
  1860. X    if (funct == LOAD) {
  1861. X    char V[80], *p;
  1862. X
  1863. X    if (fgets(V, 80, fp) && (p = index(V, '\n')))
  1864. X        *p = 0;
  1865. X    if (strcmp(V, version)) {
  1866. X        printf("Sorry, file is wrong version.");
  1867. X        return FALSE;
  1868. X    }
  1869. X        if (fscanf (fp, "persontally = %d\n", &persontally) < 1 ||
  1870. X        fscanf (fp, "comptally = %d\n", &comptally) < 1 ||
  1871. X        fscanf (fp, "Length = %d\n", &Length) < 1 ||
  1872. X        fscanf (fp, "Width = %d\n", &Width) < 1)
  1873. X        goto bad;
  1874. X    for (x = 0; x < Length * 2; ++x)
  1875. X        for (y = 0; y < Width * 2; ++y) {
  1876. X        if (fscanf (fp, "board[%*d][%*d] = %d\n", &i) < 1)
  1877. X            goto bad;
  1878. X        board[x][y] = i;
  1879. X        }
  1880. X        if (fscanf (fp, "xposit = %d\n", &xposit) < 1 ||
  1881. X        fscanf (fp, "yposit = %d\n", &yposit) < 1 ||
  1882. X        fscanf (fp, "x_start = %d\n", &x_start) < 1 ||
  1883. X        fscanf (fp, "y_start = %d\n", &y_start) < 1 ||
  1884. X        fscanf (fp, "no_good_moves = %d\n", &no_good_moves) < 1 ||
  1885. X        fscanf (fp, "control_already_established = %d\n",
  1886. X            &control_already_established) < 1 ||
  1887. X        fscanf (fp, "segtype = %d\n", &segtype) < 1 ||
  1888. X        fscanf (fp, "dX_found = %d\n", &dX_found) < 1 ||
  1889. X        fscanf (fp, "segflag = %d\n", &segflag) < 1 ||
  1890. X        fscanf (fp, "mode = %d\n", &mode) < 1 ||
  1891. X        fscanf (fp, "level = %d\n", &level) < 1 ||
  1892. X        fscanf (fp, "Bingo.x = %d, Bingo.y = %d\n",
  1893. X        &Bingo.x, &Bingo.y) < 2 ||
  1894. X        fscanf (fp, "Initial = %2s\n", Initial) < 1 ||
  1895. X        fscanf (fp, "mover = %d\n", &mover) < 1)
  1896. X        goto bad;
  1897. X    if (Length < 4 || Width < 4) {
  1898. Xbad:
  1899. X        msg("File has been corrupted.");
  1900. X        return FALSE;
  1901. X    }
  1902. X    } else {
  1903. X    (void) fprintf(fp, "%s\n", version);
  1904. X        fprintf (fp, "persontally = %d\n", persontally);
  1905. X        fprintf (fp, "comptally = %d\n", comptally);
  1906. X        fprintf (fp, "Length = %d\n", Length);
  1907. X        fprintf (fp, "Width = %d\n", Width);
  1908. X    for (x = 0; x < Length * 2; ++x)
  1909. X        for (y = 0; y < Width * 2; ++y)
  1910. X        fprintf (fp, "board[%d][%d] = %d\n", x, y, board[x][y]);
  1911. X        fprintf (fp, "xposit = %d\n", xposit);
  1912. X        fprintf (fp, "yposit = %d\n", yposit);
  1913. X        fprintf (fp, "x_start = %d\n", x_start);
  1914. X        fprintf (fp, "y_start = %d\n", y_start);
  1915. X        fprintf (fp, "no_good_moves = %d\n", no_good_moves);
  1916. X        fprintf (fp, "control_already_established = %d\n",
  1917. X              control_already_established);
  1918. X        fprintf (fp, "segtype = %d\n", segtype);
  1919. X        fprintf (fp, "dX_found = %d\n", dX_found);
  1920. X        fprintf (fp, "segflag = %d\n", segflag);
  1921. X        fprintf (fp, "mode = %d\n", mode);
  1922. X        fprintf (fp, "level = %d\n", level);
  1923. X        fprintf (fp, "Bingo.x = %d, Bingo.y = %d\n", Bingo.x, Bingo.y);
  1924. X        fprintf (fp, "Initial = %2s\n", Initial);
  1925. X        fprintf (fp, "mover = %d\n", mover);
  1926. X    }
  1927. X    return TRUE;
  1928. X}
  1929. X#if 0
  1930. X    (*funct) (&persontally, sizeof(persontally), 1, fp);
  1931. X    (*funct) (&comptally, sizeof(comptally), 1, fp);
  1932. X    (*funct) (&Length, sizeof(Length), 1, fp);
  1933. X    (*funct) (&Width, sizeof(Width), 1, fp);
  1934. X    for (x = 0; x < 120; ++x)
  1935. X    for (y = 0; y < 120; ++y) {
  1936. X        if (funct == SAVE)
  1937. X        i = board[x][y];
  1938. X        (*funct) (&i, sizeof(int), 1, fp);
  1939. X        if (funct == SAVE)
  1940. X        board[x][y] = i;
  1941. X    }
  1942. X    (*funct) (&xposit, sizeof(xposit), 1, fp);
  1943. X    (*funct) (&yposit, sizeof(yposit), 1, fp);
  1944. X    (*funct) (&x_start, sizeof(x_start), 1, fp);
  1945. X    (*funct) (&y_start, sizeof(y_start), 1, fp);
  1946. X    (*funct) (&no_good_moves, sizeof(no_good_moves), 1, fp);
  1947. X    (*funct) (&control_already_established, sizeof(control_already_established), 1, fp);
  1948. X    (*funct) (&segtype, sizeof(segtype), 1, fp);
  1949. X    (*funct) (&dX_found, sizeof(dX_found), 1, fp);
  1950. X    (*funct) (&segflag, sizeof(segflag), 1, fp);
  1951. X    (*funct) (&mode, sizeof(mode), 1, fp);
  1952. X    (*funct) (&level, sizeof(level), 1, fp);
  1953. X    (*funct) (&Bingo, sizeof(Bingo), 1, fp);
  1954. X    (*funct) (Initial, sizeof(Initial), 1, fp);
  1955. X    (*funct) (&mover, sizeof(mover), 1, fp);
  1956. X#endif
  1957. END_OF_save.c
  1958. if test 5455 -ne `wc -c <save.c`; then
  1959.     echo shar: \"save.c\" unpacked with wrong size!
  1960. fi
  1961. # end of overwriting check
  1962. fi
  1963. if test -f score.c -a "${1}" != "-c" ; then 
  1964.   echo shar: Will not over-write existing file \"score.c\"
  1965. else
  1966. echo shar: Extracting \"score.c\" \(2371 characters\)
  1967. sed "s/^X//" >score.c <<'END_OF_score.c'
  1968. X/*  SCORE.C  */
  1969. X
  1970. X#include         "dots.h"
  1971. X
  1972. X#define NAMELEN        30
  1973. X
  1974. Xstruct scores {
  1975. X    int sc_person;
  1976. X    int sc_comp;
  1977. X    char sc_name[NAMELEN];
  1978. X    int sc_level;
  1979. X    int sc_width;
  1980. X    int sc_length;
  1981. X    char sc_login[9];
  1982. X}   top_ten[10];
  1983. X
  1984. Xhigh_score(Read, names)
  1985. Xbool Read, names;
  1986. X{
  1987. X    struct scores *scp, *temp;
  1988. X    int fd;
  1989. X
  1990. X    for (scp = top_ten; scp < &top_ten[10]; scp++) {
  1991. X    scp->sc_name[0] = 0;
  1992. X    scp->sc_login[0] = 0;
  1993. X    scp->sc_length = 0;
  1994. X    scp->sc_width = 0;
  1995. X    scp->sc_person = 0;
  1996. X    scp->sc_comp = 0;
  1997. X    scp->sc_level = 0;
  1998. X    }
  1999. X
  2000. X    /* read the top ten file into the array and close the file */
  2001. X    if ((fd = open(SCOREFILE, 2)) < 0) {
  2002. X    printf("no score file\n");
  2003. X    return;
  2004. X    }
  2005. X    (void) read(fd, (char *) top_ten, sizeof(top_ten));
  2006. X
  2007. X    /* Print the list */
  2008. X    if (Read) {
  2009. X    printf("Top Players:\n");
  2010. X    printf("Level\tDimensions   Computer   Human\tName\n");
  2011. X    for (scp = top_ten; scp < &top_ten[10]; scp++)
  2012. X        if (scp->sc_person) {
  2013. X        printf("%s\t  %2d X %2d      %3d       %3d\t%s",
  2014. X            (scp->sc_level == DUMB) ?
  2015. X            "Easy" : (scp->sc_level == HARD ?
  2016. X            "Hard" : "Killer"),
  2017. X            scp->sc_width,
  2018. X            scp->sc_length, scp->sc_comp, scp->sc_person, scp->sc_name);
  2019. X        if (names)
  2020. X            printf("(%s)", scp->sc_login);
  2021. X        putchar('\n');
  2022. X        } else
  2023. X        break;
  2024. X    }
  2025. X    /* check to see if current score made it */
  2026. X    else {
  2027. X    for (scp = top_ten; scp < &top_ten[10]; scp++)
  2028. X        if (value_cmp(scp))
  2029. X        break;
  2030. X    if (scp < &top_ten[10]) {
  2031. X        char *getlogin(), *login = getlogin();
  2032. X
  2033. X        for (temp = &top_ten[9]; temp > scp; temp--)
  2034. X        *temp = *(temp - 1);
  2035. X        scp->sc_width = Width;
  2036. X        scp->sc_length = Length;
  2037. X        scp->sc_person = persontally;
  2038. X        scp->sc_comp = comptally;
  2039. X        scp->sc_level = level;
  2040. X        (void) strcpy(scp->sc_login, login);
  2041. X        addstr("--more--"), clrtoeol();
  2042. X        refresh();
  2043. X        raw(), noraw();
  2044. X        while (getchar() != ' ')
  2045. X        fputc(7, stderr);
  2046. X        msg("You made the top ten! Enter a name: ");
  2047. X        Getstr(scp->sc_name, NAMELEN - 1);
  2048. X        if (strlen(scp->sc_name) > 1) {
  2049. X        (void) lseek(fd, (long)0, 0);
  2050. X        (void) write(fd, (char *)top_ten, sizeof top_ten);
  2051. X        } else
  2052. X        msg("Nothing entered.");
  2053. X    }
  2054. X    (void) close(fd);
  2055. X    }
  2056. X}
  2057. X
  2058. Xvalue_cmp(entry)
  2059. Xstruct scores *entry;
  2060. X{
  2061. X    int value;
  2062. X
  2063. X    value = (level - entry->sc_level) * 500;
  2064. X    value += persontally + Length * Width;
  2065. X    return (value > entry->sc_length * entry->sc_width + entry->sc_person);
  2066. X}
  2067. END_OF_score.c
  2068. if test 2371 -ne `wc -c <score.c`; then
  2069.     echo shar: \"score.c\" unpacked with wrong size!
  2070. fi
  2071. # end of overwriting check
  2072. fi
  2073. if test -f sockt.c -a "${1}" != "-c" ; then 
  2074.   echo shar: Will not over-write existing file \"sockt.c\"
  2075. else
  2076. echo shar: Extracting \"sockt.c\" \(4229 characters\)
  2077. sed "s/^X//" >sockt.c <<'END_OF_sockt.c'
  2078. X/* sockt.c */
  2079. X/* All the stuff that deals with sockets is here */
  2080. X
  2081. X#include "dots.h"
  2082. X#include <sys/un.h>    /* unix domain sockets */
  2083. X#include <errno.h>
  2084. X
  2085. X#define SOCKNAME  "/tmp/dots"
  2086. X
  2087. X#define namelen(sockt) (sizeof (sockt.sun_family) + strlen(sockt.sun_path))
  2088. X
  2089. Xint len;
  2090. Xstatic int (*oldint)(), (*oldquit)();
  2091. Xstruct sockaddr_un sockt;
  2092. X
  2093. Xsockit(argc, argv)
  2094. Xchar **argv;
  2095. X{
  2096. X    setbuf(stdout, (char *)NULL);
  2097. X
  2098. X    mover = THEM;
  2099. X    opponent = argv[2];
  2100. X    Initial[THEM] = *opponent;
  2101. X
  2102. X    (void) strcpy(sockt.sun_path, SOCKNAME);
  2103. X    len = namelen(sockt);
  2104. X
  2105. X    if ((sd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {    /* create a socket */
  2106. X    oops("Socket error");
  2107. X    return;
  2108. X    }
  2109. X
  2110. X    /* try to respond to a possible connection already established */
  2111. X    while (connect(sd, (struct sockaddr *)&sockt, namelen(sockt)) == -1)
  2112. X    /*
  2113. X     * check to see if we can't connect because of "correct" errors 
  2114. X     */
  2115. X    if (errno != ENOENT) {    /* no such file or directory */
  2116. X        perror("connect on socket");
  2117. X        puts("Trying again...");
  2118. X        (void) close(sd);
  2119. X        sockit(argc, argv);
  2120. X    } else {
  2121. X        mover = US;    /* challenger goes first */
  2122. X        if (!findem(argc, argv))
  2123. X        return;
  2124. X        else
  2125. X        break;
  2126. X    }
  2127. X    getsizes();        /* get the window sizes of both players */
  2128. X    Dots(2);        /* we are connected and won't return */
  2129. X}
  2130. X
  2131. X/* send an invitation */
  2132. X
  2133. X#include <sys/time.h>
  2134. Xstruct itimerval waittime;
  2135. Xjmp_buf jmpbuf;
  2136. X
  2137. Xreinvite(sig)
  2138. X{
  2139. X    if (sig == SIGALRM) {
  2140. X    printf("\nre");
  2141. X    longjmp(jmpbuf, 1);
  2142. X    }
  2143. X    timerclear(&waittime.it_interval);
  2144. X    timerclear(&waittime.it_value);
  2145. X    (void) setitimer(ITIMER_REAL, &waittime, (struct itimerval *) 0);
  2146. X    destroysocket();
  2147. X    (void) signal(SIGINT, oldint);
  2148. X    (void) signal(SIGQUIT, oldquit);
  2149. X    longjmp(jmpbuf, 2);
  2150. X}
  2151. X
  2152. Xinvite(recipient)
  2153. XFILE *recipient;
  2154. X{
  2155. X    int newsok;
  2156. X
  2157. X    waittime.it_value.tv_sec = 30;
  2158. X    waittime.it_value.tv_usec = 0;
  2159. X    waittime.it_interval = waittime.it_value;
  2160. X
  2161. X    /*
  2162. X     * we're a server, so we give a name to the socket to the client knows
  2163. X     * what to connect with. bind() is used to give a name to a socket. 
  2164. X     */
  2165. X    if (bind(sd, (struct sockaddr *)&sockt, len) == -1) {
  2166. X    oops("Can't bind %s", SOCKNAME);
  2167. X    return 0;
  2168. X    }
  2169. X    if (listen(sd, 5) == -1) {
  2170. X    oops("Can't listen %s", SOCKNAME);
  2171. X    return 0;
  2172. X    }
  2173. X
  2174. X    setbuf(recipient, (char *)NULL);
  2175. X
  2176. X    /*
  2177. X     * accept() will hang around and do nothing unless someone requests a
  2178. X     * connection.  So, we wait..  signal again every 30 secs with setitmer 
  2179. X     */
  2180. X    (void) signal(SIGALRM, reinvite);
  2181. X    oldint = signal(SIGINT, reinvite);
  2182. X    oldquit = signal(SIGQUIT, reinvite);
  2183. X    (void) setitimer(ITIMER_REAL, &waittime, (struct itimerval *) 0);
  2184. X    if (setjmp(jmpbuf) == 2)
  2185. X    return 0;
  2186. X    printf("sending challenge...");
  2187. X    fprintf(recipient, "Message from the \"dots\" game...\007\007\007\n");
  2188. X    fprintf(recipient, "%s would like to play \"dots.\"\n", username);
  2189. X    fprintf(recipient, "respond with \"dots 2 %s\"\n", username);
  2190. X
  2191. X    while ((newsok = accept(sd, (struct sockaddr *)0, (int *)0)) == -1)
  2192. X    if (errno != EINTR) {
  2193. X        oops("Can't accept %s", SOCKNAME);
  2194. X        return 0;
  2195. X    } else
  2196. X        continue;
  2197. X
  2198. X    timerclear(&waittime.it_interval);
  2199. X    timerclear(&waittime.it_value);
  2200. X    (void) setitimer(ITIMER_REAL, &waittime, (struct itimerval *) 0);
  2201. X    (void) close(sd);
  2202. X    sd = newsok;
  2203. X    return 1;
  2204. X}
  2205. X
  2206. X /* find lines and cols of the other guy */
  2207. Xgetsizes()
  2208. X{
  2209. X    int their_lines, their_cols;
  2210. X
  2211. X    do_twice {
  2212. X    if (mover == US) {
  2213. X        (void) write(sd, (char *)&COLS, sizeof(int));
  2214. X        (void) write(sd, (char *)&LINES, sizeof(int));
  2215. X    } else {
  2216. X        (void) read(sd, (char *)&their_cols, sizeof(int));
  2217. X        (void) read(sd, (char *)&their_lines, sizeof(int));
  2218. X    }
  2219. X    mover = !mover;
  2220. X    }
  2221. X    Length = min(COLS, their_cols) / 4;
  2222. X    Width = min(LINES, their_lines) / 2 - 2;
  2223. X    comptally = persontally = 0;
  2224. X    xposit = 2, yposit = 1;
  2225. X    y_start = 1 + (LINES - 2) / 2 - Width;
  2226. X    x_start = 1 + COLS / 2 - Length * 2;
  2227. X
  2228. X    (void) signal(SIGINT, oldint);
  2229. X    (void) signal(SIGQUIT, oldquit);
  2230. X}
  2231. X
  2232. Xdestroysocket()
  2233. X{
  2234. X    if (!access(SOCKNAME, 0)) {
  2235. X    if (shutdown(sd, 2) == -1)  /* dissallow further sends and recieves */
  2236. X        oops("shutdown failed cuz");
  2237. X    if (unlink(SOCKNAME) == -1)
  2238. X        oops("Can't unlink %s", SOCKNAME);
  2239. X    }
  2240. X}
  2241. END_OF_sockt.c
  2242. if test 4229 -ne `wc -c <sockt.c`; then
  2243.     echo shar: \"sockt.c\" unpacked with wrong size!
  2244. fi
  2245. # end of overwriting check
  2246. fi
  2247. echo shar: End of shell archive.
  2248. exit 0
  2249.